package com.yami.shop.mystery.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.dto.AsyncAddCoinDTO;
import com.yami.shop.bean.enums.EsOperationType;
import com.yami.shop.bean.enums.ProdType;
import com.yami.shop.bean.event.ActivityProdChangeStatusEvent;
import com.yami.shop.bean.event.ActivityRemoveChangeStatusEvent;
import com.yami.shop.bean.event.EsProductUpdateEvent;
import com.yami.shop.bean.model.OrderItem;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.ShopDealer;
import com.yami.shop.bean.vo.search.MicroreleaseProductSearchVo;
import com.yami.shop.common.bean.PageDTO;
import com.yami.shop.common.bean.PageVO;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.PageUtil;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.mystery.common.dao.ActivityPresellMapper;
import com.yami.shop.mystery.common.dao.ActivitySubjectMapper;
import com.yami.shop.mystery.common.dto.ActivityPresellDto;
import com.yami.shop.mystery.common.dto.ActivityProdDataDto;
import com.yami.shop.mystery.common.dto.ActivityProdDto;
import com.yami.shop.mystery.common.enums.ActivityEnum;
import com.yami.shop.mystery.common.enums.ActivityRuleEnum;
import com.yami.shop.mystery.common.model.*;
import com.yami.shop.mystery.common.service.*;
import com.yami.shop.mystery.common.vo.ActivityPresellPageVo;
import com.yami.shop.nft.common.service.NftDawService;
import com.yami.shop.security.common.util.AuthUserContext;
import com.yami.shop.service.OrderItemService;
import com.yami.shop.service.ProductService;
import com.yami.shop.service.ShopDealerService;
import groovy.lang.Tuple;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 活动业务实现类
 *
 * @author wxf
 * @date 2023/4/12 10:56
 */
@Service
@AllArgsConstructor
@Slf4j
public class ActivityPresellServiceImpl extends ServiceImpl<ActivityPresellMapper, ActivityPresell> implements ActivityPresellService {

    private final ActivityPresellMapper presellMapper;

    private final ActivityProdService activityProdService;

    private final MysteryBoxService mysteryBoxService;

    private final ProductService productService;

    private final ApplicationEventPublisher eventPublisher;

    private final MysteryBoxExtensionService mysteryBoxExtensionService;

    private final ActivityRuleService activityRuleService;

    private final OrderItemService orderItemService;

    private final ActivitySubjectMapper activitySubjectMapper;

    private final NftDawService nftDawService;

    private final ShopDealerService shopDealerService;

    private final static String ACTIVITY_SKU_STOCKS_PREFIX = "ACTIVITY_SKU_STOCKS_";

    @Override
    public PageVO<ActivityPresellDto> pageList(PageDTO pageDTO, ActivityPresellPageVo dto) {
        return PageUtil.doPage(pageDTO, () -> presellMapper.pageList(dto));
    }

    private void checkActivityTime(String name, Date activityStart, Date activityEnd, Date putawayTime, List<ActivityRule> list) {
        if (ObjectUtil.isEmpty(list)) {
            throw new YamiShopBindException(String.format("%s规则不能为空", name));
        }
        ActivityRule rule = list.get(0);
        if (activityStart.getTime() > rule.getStartTime().getTime() || activityEnd.getTime() < rule.getStartTime().getTime() || activityStart.getTime() > rule.getEndTime().getTime() || activityEnd.getTime() < rule.getEndTime().getTime()) {
            throw new YamiShopBindException(String.format("%s规则时间不再活动时间内", name));
        }
        if (rule.getStartTime().getTime() > putawayTime.getTime() || rule.getEndTime().getTime() > putawayTime.getTime()) {
            throw new YamiShopBindException(String.format("%s规则时间不能早于商品上架时间", name));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveOrUpdate(ActivityPresellDto dto) {
        if (dto.getActivityType().equals("6")) {
            List<ActivityPresell> list2 = super.list(new LambdaQueryWrapper<ActivityPresell>().in(ActivityPresell::getStatus, 0, 1, 2).eq(ActivityPresell::getActivityType, "6").ge(ActivityPresell::getActivityEndTime, dto.getActivityEndTime()).le(ActivityPresell::getActivityStartTime, dto.getActivityStartTime()));
            if (CollUtil.isNotEmpty(list2)) {
                throw new YamiShopBindException("该时间段内存在邀请活动");
            }
        }

        if (dto.getActivityType().equals("1")) {
            for (ActivityProdDto prodDto : dto.getProds()) {
                ActivityPresell activityPresell = presellMapper.selectDataByProdIdAndActivityId(prodDto.getProdId(), null, dto.getActivityStartTime(), dto.getActivityEndTime(), dto.getActivityType(), dto.getShopDealerId());
                if (ObjectUtil.isNotNull(activityPresell)) {
                    throw new YamiShopBindException("该时间段内存在该经销商相同商品的其他预售活动,请检查配置！");
                }
            }
        }
        List<ActivityRule> ruleList = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(dto.getActivityRule())) {
            ruleList = activityRuleService.selectByRuleId(dto.getActivityRule());
        }
        List<ActivityRule> discounts = ruleList.stream().filter(a -> a.getRuleType().equals(ActivityRuleEnum.DISCOUNTS.getValue())).collect(Collectors.toList());
        List<ActivityRule> preemption = ruleList.stream().filter(a -> a.getRuleType().equals(ActivityRuleEnum.PREEMPTION.getValue())).collect(Collectors.toList());
        if (dto.getIsDiscounts() == 1 && dto.getIsPreemption() == 0) { //只有优惠购
            checkActivityTime("优惠购", dto.getActivityStartTime(), dto.getActivityEndTime(), dto.getPutawayTime(), discounts);
        } else if (dto.getIsDiscounts() == 0 && dto.getIsPreemption() == 1) { //只有优先购
            checkActivityTime("优先购", dto.getActivityStartTime(), dto.getActivityEndTime(), dto.getPutawayTime(), preemption);
        } else if (dto.getIsDiscounts() == 1 && dto.getIsPreemption() == 1) { //优惠购、优先购都有
            checkActivityTime("优惠购", dto.getActivityStartTime(), dto.getActivityEndTime(), dto.getPutawayTime(), discounts);
            checkActivityTime("优先购", dto.getActivityStartTime(), dto.getActivityEndTime(), dto.getPutawayTime(), preemption);
            ActivityRule discountsRule = discounts.get(0);
            ActivityRule preemptionRule = preemption.get(0);
            if (preemptionRule.getStartTime().getTime() < discountsRule.getStartTime().getTime() || preemptionRule.getStartTime().getTime() < discountsRule.getEndTime().getTime() || preemptionRule.getEndTime().getTime() < discountsRule.getStartTime().getTime() || preemptionRule.getEndTime().getTime() < discountsRule.getEndTime().getTime()) {
                throw new YamiShopBindException("优先购规则时间不能早于优惠购规则时间");
            }
        }

        ActivityPresell bean = BeanUtil.copyProperties(dto, ActivityPresell.class);
        Map<Long, ActivityProd> oldActivityProdMap = new HashMap<>();
        //删除旧数据
        if (ObjectUtils.isNotEmpty(bean.getId())) {
            List<ActivityProd> oldActivityProds = activityProdService.list(Wrappers.lambdaUpdate(ActivityProd.class).eq(ActivityProd::getActivityId, bean.getId()).eq(ActivityProd::getIsDel, 0).orderByDesc(ActivityProd::getAlreadyReplenishmentQuantity));
            oldActivityProdMap = oldActivityProds.stream().collect(Collectors.toMap(s -> s.getProdId(), v -> v));
            activityProdService.update(Wrappers.lambdaUpdate(ActivityProd.class).eq(ActivityProd::getActivityId, bean.getId()).eq(ActivityProd::getIsDel, 0).set(ActivityProd::getIsDel, 1));
        }
        List<ActivityProd> prods = new ArrayList<>();
        if (dto.getActivityType().equals("2")) {
            bean.setProdNum(dto.getActivityIds().split(",").length);
        } else {
            bean.setProdNum(dto.getProds().size());
        }
        bean.setShopId(AuthUserContext.get().getShopId());
        List<ActivityPresell> list2 = super.list(new LambdaQueryWrapper<ActivityPresell>().eq(ActivityPresell::getActivityName, bean.getActivityName()).eq(ActivityPresell::getDelFlag, 0).eq(ActivityPresell::getActivityType, bean.getActivityType()).eq(ActivityPresell::getShopId, bean.getShopId()).notIn(ObjectUtils.isNotEmpty(bean.getId()), ActivityPresell::getId, bean.getId()));
        if (CollUtil.isNotEmpty(list2)) {
            throw new YamiShopBindException("活动名称不能重复");
        }
        //获取经销商信息
        ShopDealer shopDealer = null;
        if(ObjectUtil.isNotEmpty(dto.getShopDealerId())){
            shopDealer = shopDealerService.getShopDealerById(dto.getShopDealerId().intValue());
        }


        Integer originStocks = 0;
        Integer totalStocks = 0;
        if (dto.getActivityType().equals("2")) {
            for (String activityId : dto.getActivityIds().split(",")) {
                ActivityProd activityProd = new ActivityProd();
                activityProd.setProdId(Long.parseLong(activityId));
                prods.add(activityProd);
            }
        } else {
            for (ActivityProdDto prodDto : dto.getProds()) {
                if (dto.getActivityType().equals("1")) {
                    // 查询该商品参与活动的有效库存数
                    Integer allStocks = presellMapper.selectStocksByProdId(prodDto.getProdId());
                    // 判断该商品是否还有库存机库存是否还满足本次活动预扣减
                    Product productInfo = productService.getProductInfo(prodDto.getProdId());
                    Integer stocks = productInfo.getTotalStocks() - allStocks;
                    if (productInfo.getTotalStocks() <= 0 || stocks <= 0 || stocks < prodDto.getProdOriginStocks()) {
                        throw new YamiShopBindException("该商品剩余库存为：" + stocks + ",本次活动库存为：" + prodDto.getProdOriginStocks() + "，商品库存不足！");
                    }
                }

                //预售活动商品上架、摇奖
                eventPublisher.publishEvent(new ActivityProdChangeStatusEvent(bean.getId(), bean.getActivityType(), prodDto.getProdId(), bean.getShopId()));
                ActivityProd activityProd = new ActivityProd();
                activityProd.setProdId(prodDto.getProdId());
                activityProd.setPreemptionPrice((long) (ObjectUtil.isEmpty(prodDto.getPreemptionPrice()) ? 0 : prodDto.getPreemptionPrice() * 100));
                activityProd.setProdOriginStocks(ObjectUtil.isEmpty(prodDto.getProdOriginStocks())? 0:prodDto.getProdOriginStocks().intValue());
                activityProd.setProdTotalStocks(ObjectUtil.isEmpty(prodDto.getProdTotalStocks())? 0:prodDto.getProdTotalStocks().intValue());
                activityProd.setPurchaseNum(prodDto.getPurchaseNum());
                if (ObjectUtils.isNotEmpty(bean.getId())) {
                    ActivityProd oldActivityProd = oldActivityProdMap.get(prodDto.getProdId());
                    if (oldActivityProd.getProdOriginStocks() < prodDto.getProdOriginStocks().intValue()) {
                        activityProd.setAlreadyReplenishmentQuantity(oldActivityProd.getAlreadyReplenishmentQuantity() + (prodDto.getProdOriginStocks().intValue() - oldActivityProd.getProdOriginStocks()));
                    } else {
                        activityProd.setAlreadyReplenishmentQuantity(oldActivityProd.getAlreadyReplenishmentQuantity());
                    }
                } else {
                    activityProd.setAlreadyReplenishmentQuantity(0);
                }
                if(ObjectUtil.isNotNull(prodDto.getProdOriginStocks())){
                    originStocks += prodDto.getProdOriginStocks().intValue();
                    totalStocks += prodDto.getProdTotalStocks().intValue();
                }
                prods.add(activityProd);

                if (dto.getActivityType().equals("1")) {
                    log.info("商品提交的原始库存数{},默认激活比例{}", prodDto.getProdOriginStocks().intValue(), dto.getProportion());
                    // 激活默认证书
                    if (ObjectUtil.isNotNull(dto.getProportion()) && dto.getProportion() > 0 && ObjectUtil.isNotNull(shopDealer) && ObjectUtil.isNotNull(shopDealer.getDealerCode())) {
                        AsyncAddCoinDTO asyncAddCoinDTO = new AsyncAddCoinDTO();
                        // 修改活动数据的情况
                        if (ObjectUtils.isNotEmpty(bean.getId())) {
                            ActivityProd oldActivityProd = oldActivityProdMap.get(prodDto.getProdId());
                            // 库存增加，补证书
                            if (oldActivityProd.getProdOriginStocks() < prodDto.getProdOriginStocks().intValue()) {
                                // 先查询该经销商活动已经激活的证书数量
                                Long activityNum = nftDawService.asyncIsHaveCoin(prodDto.getProdId(), null, shopDealer.getDealerCode(),true);
                                log.info("查询到已激活币数量为{}", activityNum);
                                // 计算应该补齐证书的数量
                                Integer applyNum = prodDto.getProdOriginStocks().intValue() - activityNum.intValue();
                                log.info("库存增加，追补证书数量为{}", activityNum);
                                asyncAddCoinDTO.setApplyNum(applyNum);
                            }
                            // 库存没变，激活比例增加
                            if (oldActivityProd.getProdOriginStocks() == prodDto.getProdOriginStocks().intValue()) {
                                ActivityPresell activityPresell = super.getById(bean.getId());
                                if (ObjectUtil.isNotNull(activityPresell.getProportion()) && activityPresell.getProportion() > 0) {
                                    if (dto.getProportion() > activityPresell.getProportion()) {
                                        // 先查询该经销商活动已经激活的证书数量
                                        Long activityNum = nftDawService.asyncIsHaveCoin(prodDto.getProdId(), null, shopDealer.getDealerCode(),true);
                                        log.info("查询到已激活币数量为{}", activityNum);
                                        double result = Math.ceil(prodDto.getProdOriginStocks().intValue() * (dto.getProportion() / 100d));
                                        if(result > activityNum.intValue()){
                                            log.info("激活比例增加，需要补充证书数量为{}", (int) result - activityNum.intValue());
                                            asyncAddCoinDTO.setApplyNum((int) result - activityNum.intValue());
                                        }
                                    }
                                }
                            }
                        }
                        // 新增活动数据的情况
                        else {
                            double result = Math.ceil(prodDto.getProdOriginStocks().intValue() * (dto.getProportion() / 100d));
                            log.info("新增活动默认激活证书数量为{}", result);
                            asyncAddCoinDTO.setApplyNum((int) result);
                        }
                        log.info("请求激活铸币的数量{}", asyncAddCoinDTO.getApplyNum());
                        if (ObjectUtil.isNotNull(asyncAddCoinDTO.getApplyNum()) && asyncAddCoinDTO.getApplyNum() > 0) {
                            asyncAddCoinDTO.setPrefixCode(shopDealer.getDealerCode());
                            asyncAddCoinDTO.setProdId(prodDto.getProdId());
                            nftDawService.asyncAddCoin(asyncAddCoinDTO);
                        }
                    }
                }
                // 清除缓存 更新商品库存
                productService.removeProdCacheByProdId(prodDto.getProdId());
                eventPublisher.publishEvent(new EsProductUpdateEvent(prodDto.getProdId(), null, EsOperationType.UPDATE));
            }
        }
        bean.setOriginStocks(originStocks);
        bean.setTotalStocks(totalStocks);
        boolean saveOrUpdateStatus = super.saveOrUpdate(bean);
        //活动关联商品 关联表新增
        prods.forEach(s -> s.setActivityId(bean.getId()));
        activityProdService.saveBatch(prods);
        return saveOrUpdateStatus;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeIds(List<Long> ids) {
        // 1. 逻辑删除活动
        List<ActivityPresell> data = ids.stream().map(id -> new ActivityPresell(id, "1")).collect(Collectors.toList());
        this.updateBatchById(data);

        // 2. 修改产品状态为用户不可见,并且删除定时任务
        List<ActivityPresell> list = this.listByIds(data.stream().map(ActivityPresell::getId).collect(Collectors.toList()));
        for (ActivityPresell activityResell : list) {
            if (activityResell.getStatus() == 4) {
                continue;
            }
            //获取商品ID
            List<ActivityProd> prods = activityProdService.listByActivityId(activityResell.getId());
            List<Long> prodIds = prods.stream().map(a -> a.getProdId()).collect(Collectors.toList());
            Integer status = 0;
            if ("3".equals(activityResell.getActivityType())) {
                status = 1;
            }
            eventPublisher.publishEvent(new ActivityRemoveChangeStatusEvent(0, status, prodIds, activityResell.getActivityType()));
        }
    }

    @Override
    public ActivityPresellDto detail(Long id) {
        ActivityPresell detail = super.getById(id);
        List<ActivityProdDto> productVos = new ArrayList<>();
        ActivityPresellDto vo = BeanUtil.copyProperties(detail, ActivityPresellDto.class);
        //获取商品ID
        List<ActivityProd> prodId = activityProdService.listByActivityId(id);
        prodId.forEach(prod -> {
            if (detail.getBlindType() == 1) { // 盲盒
                MysteryBox byId = mysteryBoxService.getById(prod.getProdId());
                ActivityProdDto productDto = BeanUtil.copyProperties(prod, ActivityProdDto.class);
                productDto.setProdName(byId.getProdName());
                productDto.setPic(byId.getPic());
                productVos.add(productDto);
            } else if (detail.getBlindType() == 0) { // 商品
                Product product = productService.getProductById(prod.getProdId());
                ActivityProdDto productDto = BeanUtil.copyProperties(product, ActivityProdDto.class);
                productDto.setImg(product.getPic());
                BigDecimal pric = new BigDecimal(prod.getPreemptionPrice() + "").divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
                productDto.setPreemptionPrice(pric.doubleValue());
                // 原始库存
                productDto.setProdOriginStocks(ObjectUtil.isNotNull(prod.getProdOriginStocks()) ? prod.getProdOriginStocks().longValue() : 0);
                // 查看以及修改 库存 为活动剩余库存
                productDto.setProdTotalStocks(ObjectUtil.isNotNull(prod.getProdTotalStocks()) ? prod.getProdTotalStocks().longValue() : 0);
                // 原商品库存为 商品总库存减去 已经 配置的活动库存
                Integer activityStocks = presellMapper.selectStocksByProdId(product.getProdId());
                productDto.setTotalStocks(product.getTotalStocks().longValue() - activityStocks);
                productDto.setPurchaseNum(prod.getPurchaseNum());
                productDto.setLinkAddr(prod.getLinkAddr());
                productDto.setQrcodeAddr(prod.getQrcodeAddr());

                productVos.add(productDto);
            }
        });
        vo.setProds(productVos);
        ruleToActivityPresell(vo);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ActivityPresell> invalidByShopId(Long shopId) {

        // 获取正在进行中的活动
        List<ActivityPresell> activityPresells = presellMapper.selectList(Wrappers.lambdaQuery(ActivityPresell.class).eq(ActivityPresell::getShopId, shopId).eq(ActivityPresell::getDelFlag, 0).eq(ActivityPresell::getStatus, ActivityEnum.NORMAL.getValue()));
        if (CollUtil.isEmpty(activityPresells)) {
            return new ArrayList<>();
        }
        List<Long> activityIds = new ArrayList<>();
        List<Long> boxIds = new ArrayList<>();
        List<Long> prodIds = new ArrayList<>();
        for (ActivityPresell activity : activityPresells) {
            activityIds.add(activity.getId());
            List<ActivityProd> prodId = activityProdService.listByActivityId(activity.getId());
            prodId.forEach(prod -> {
                if (activity.getActivityType().equals("3")) { // 盲盒活动
                    List<MysteryBoxExtension> prods = mysteryBoxExtensionService.list(new LambdaQueryWrapper<MysteryBoxExtension>().eq(MysteryBoxExtension::getBid, prod.getProdId()));
                    List<Long> ids = prods.stream().filter(p -> p.getPid() != -1).map(m -> m.getPid()).distinct().collect(Collectors.toList());
                    prodIds.addAll(ids);
                    boxIds.add(prod.getProdId());
                } else if (activity.getActivityType().equals("1")) { //预售活动
                    prodIds.add(prod.getProdId());
                }
            });
        }
        // 将商品变回普通商品
        productService.update(Wrappers.lambdaUpdate(Product.class).set(Product::getActivityId, 0L).set(Product::getProdType, ProdType.PROD_TYPE_NORMAL.value()).in(Product::getProdId, prodIds));
        // 失效秒杀活动
        update(Wrappers.lambdaUpdate(ActivityPresell.class).set(ActivityPresell::getStatus, ActivityEnum.INVALID.getValue()).in(ActivityPresell::getId, activityIds));
        // 盲盒盒子更新为失效
        mysteryBoxService.update(Wrappers.lambdaUpdate(MysteryBox.class).set(MysteryBox::getStatus, ActivityEnum.INVALID.getValue()).in(MysteryBox::getId, boxIds));
        // 更新es中的商品数据
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, prodIds, EsOperationType.UPDATE));
        return activityPresells;
    }

    @Override
    public List<ActivityPresellDto> getList(String activityId) {
        // 获取已经绑定的活动ID
        List<ActivitySubject> list = activitySubjectMapper.selectList(new QueryWrapper<ActivitySubject>());
        String activityIds = list.stream().map(ActivitySubject::getActivityId).collect(Collectors.joining(","));
        List<String> activityIdLits = Arrays.asList(activityIds.split(","));
        if (ObjectUtil.isNotEmpty(activityId)) {
            activityIdLits = activityIdLits.stream().filter(s -> !Arrays.asList(activityId.split(",")).contains(s)).collect(Collectors.toList());
        }

        List<ActivityPresell> activityPresells = presellMapper.selectList(new LambdaQueryWrapper<ActivityPresell>().ge(ActivityPresell::getActivityEndTime, new Date()).eq(ActivityPresell::getDelFlag, "0").eq(ActivityPresell::getShopId, AuthUserContext.get().getShopId()).notIn(ActivityPresell::getId, activityIdLits).orderByDesc(ActivityPresell::getActivityEndTime));
        return BeanUtil.copyToList(activityPresells, ActivityPresellDto.class);
    }

    @Override
    public List<ActivityPresellDto> getAutoReplenishList() {
        List<ActivityPresell> activityPresells = presellMapper.selectList(new LambdaQueryWrapper<ActivityPresell>().ge(ActivityPresell::getActivityEndTime, new Date()).eq(ActivityPresell::getDelFlag, "0").eq(ActivityPresell::getIsAutoReplenish, 1l).orderByDesc(ActivityPresell::getActivityEndTime));
        return BeanUtil.copyToList(activityPresells, ActivityPresellDto.class);
    }

    /**
     * 获取活动时间内的活动列表
     *
     * @param activityType
     * @return
     */
    @Override
    public List<ActivityPresellDto> selectAllActivityPresellByActivityType(Integer activityType) {
        List<ActivityPresellDto> presells = presellMapper.selectAllActivityPresellByActivityType(activityType);
        for (ActivityPresellDto dto : presells) {
            ruleToActivityPresell(dto);
        }
        return presells;
    }

    @Override
    public List<ActivityPresellDto> selectAllActivityPresellByProdId(Long prodId) {
        List<ActivityPresellDto> presells = presellMapper.selectAllActivityPresell(prodId);
        for (ActivityPresellDto dto : presells) {
            ruleToActivityPresell(dto);
        }
        return presells;
    }

    /**
     * 将规则信息填充到活动dto对象中
     *
     * @param dto
     */
    private void ruleToActivityPresell(ActivityPresellDto dto) {

        List<ActivityRule> ruleList = activityRuleService.selectByRuleId(dto.getActivityRule());
        // 按规则类型转分组
        Map<String, List<ActivityRule>> map = ruleList.stream().collect(Collectors.groupingBy(ActivityRule::getRuleType));

        Map<String, Boolean> ruleMap = new HashMap<>();
        for (Map.Entry<String, List<ActivityRule>> rules : map.entrySet()) {
            singleRuleToActivityPresell(rules.getKey(), rules.getValue(), dto, ruleMap);
        }
        if (ruleMap.get(ActivityRuleEnum.DISCOUNTS.getValue()) != null && ruleMap.get(ActivityRuleEnum.DISCOUNTS.getValue())) {
            dto.setMaxNum(dto.getDiscountsNum());
            dto.setRuleMaxNum(dto.getDiscountsNum());
        } else if (ruleMap.get(ActivityRuleEnum.PREEMPTION.getValue()) != null && ruleMap.get(ActivityRuleEnum.PREEMPTION.getValue())) {
            dto.setMaxNum(dto.getPreemptionNum());
            dto.setRuleMaxNum(dto.getPreemptionNum());
        } else {
            dto.setMaxNum(dto.getPurchaseNum());
            dto.setRuleMaxNum(dto.getPurchaseNum());
        }

        // 前端页面参数用
        List<Long> discountsRule = ruleList.stream().filter(a -> a.getRuleType().equals(ActivityRuleEnum.DISCOUNTS.getValue())).map(a -> a.getRuleId()).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(discountsRule)) {
            dto.setDiscountsRule(discountsRule.get(0));
        }
        List<Long> preemptionRule = ruleList.stream().filter(a -> a.getRuleType().equals(ActivityRuleEnum.PREEMPTION.getValue())).map(a -> a.getRuleId()).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(preemptionRule)) {
            dto.setPreemptionRule(preemptionRule.get(0));
        }
    }

    /**
     * 将规则信息填充到活动dto对象中
     *
     * @param ruleType
     * @param list
     * @param dto
     */
    private void singleRuleToActivityPresell(String ruleType, List<ActivityRule> list, ActivityPresellDto dto, Map<String, Boolean> ruleMap) {

        if (ObjectUtils.isEmpty(list)) {
            return;
        }
        ActivityRule rule = list.get(0);
        Tuple tuple = activityRuleService.ruleCheck(list, ruleType);
        boolean check = (boolean) tuple.get(0); // 规则满足条件
        if (check) {
            rule = (ActivityRule) tuple.get(3);
        }
        ActivityRuleEnum ruleEnum = ActivityRuleEnum.instance(ruleType);
        switch (ruleEnum) {
            case PREEMPTION: //优先购
                if (dto.getIsPreemption() == 1) {
                    dto.setPreemptionStartTime(rule.getStartTime());
                    dto.setPreemptionEndTime(rule.getEndTime());
                    dto.setPreemptionNum(rule.getConditionNum().intValue());
                    ruleMap.put(ruleType, check);
                }
                break;
            case DISCOUNTS: //优惠购
                if (dto.getIsDiscounts() == 1) {
                    dto.setDiscountsStartTime(rule.getStartTime());
                    dto.setDiscountsEndTime(rule.getEndTime());
                    dto.setDiscountsNum(rule.getConditionNum().intValue());
                    ruleMap.put(ruleType, check);
                }
                break;
            case APPLY: //报名
                if (dto.getIsApply() == 1) {
                    dto.setApplyStartTime(rule.getStartTime());
                    dto.setApplyEndTime(rule.getEndTime());
                }
                break;
            case INVITENUM: //邀请人数

                break;
            case PAYMENTAMOUNT: //支付金额

                break;
            case PAYMENTTIME: // 最近支付时间

                break;
            case REGISTERTIME: // 注册时间

                break;
            case PAYMENTNUM: //支付次数

                break;
            case HOLDPRODUCT: //持有艺术品

                break;
            case AUTOREPLENISH: //自动补货
                dto.setReplenishmentQuantity(rule.getReplenishmentQuantity());
                dto.setReplenishmentThreshold(rule.getReplenishmentThreshold());
                dto.setMaxReplenishmentQuantity(rule.getMaxReplenishmentQuantity());
                break;
            default:

        }
    }

    @Override
    public List<ActivityProdDto> getPutawayProdId() {
        return presellMapper.getPutawayProdId();
    }

    @Override
    public List<ActivityPresellDto> selectAllActivityPresellByActivityTypes(List<Long> activityTypes) {

        return presellMapper.selectAllActivityPresellByActivityTypes(activityTypes);
    }

    @Override
    public List<ActivityPresellDto> selectAllActivityPresellByActivityIds(List<String> activityIds, List<Long> activitys) {
        return presellMapper.selectAllActivityPresellByActivityIds(activityIds, activitys);
    }

    @Override
    public boolean saveOrUpdateNewcomerRewards(ActivityPresellDto dto) {
        if (dto.getActivityType().equals("7") && 1 == dto.getBlindType()) {
            throw new YamiShopBindException("注册奖励无法选择商品");
        }
        List<ActivityPresell> list = super.list(new LambdaQueryWrapper<ActivityPresell>().in(ActivityPresell::getStatus, 0, 1, 2).in(ActivityPresell::getActivityType, "7", "8").ge(ActivityPresell::getActivityEndTime, dto.getActivityEndTime()).le(ActivityPresell::getActivityStartTime, dto.getActivityStartTime()));
        if (CollUtil.isNotEmpty(list)) {
            throw new YamiShopBindException("该时间段内存在新人奖励活动");
        }
        ActivityPresell bean = BeanUtil.copyProperties(dto, ActivityPresell.class);
        //删除旧数据
        if (ObjectUtils.isNotEmpty(bean.getId())) {
            activityProdService.update(Wrappers.lambdaUpdate(ActivityProd.class).eq(ActivityProd::getActivityId, bean.getId()).eq(ActivityProd::getIsDel, 0).set(ActivityProd::getIsDel, 1));
        }

        List<ActivityProd> prods = new ArrayList<>();
        bean.setProdNum(dto.getProds().size());
        bean.setShopId(AuthUserContext.get().getShopId());
        List<ActivityPresell> list2 = super.list(new LambdaQueryWrapper<ActivityPresell>().eq(ActivityPresell::getActivityName, bean.getActivityName()).eq(ActivityPresell::getDelFlag, 0).eq(ActivityPresell::getActivityType, bean.getActivityType()).eq(ActivityPresell::getShopId, bean.getShopId()).notIn(ObjectUtils.isNotEmpty(bean.getId()), ActivityPresell::getId, bean.getId()));
        if (CollUtil.isNotEmpty(list2)) {
            throw new YamiShopBindException("活动名称不能重复");
        }
        boolean saveOrUpdateStatus = super.saveOrUpdate(bean);
        dto.setId(bean.getId());

        for (ActivityProdDto prodDto : dto.getProds()) {
            ActivityProd activityProd = new ActivityProd();
            activityProd.setActivityId(bean.getId());
            activityProd.setProdId(prodDto.getProdId());
            activityProd.setPreemptionPrice((long) (ObjectUtil.isEmpty(prodDto.getPreemptionPrice()) ? 0 : prodDto.getPreemptionPrice() * 100));
            prods.add(activityProd);
        }
        //活动关联商品 关联表新增
        activityProdService.saveBatch(prods);
        return saveOrUpdateStatus;
    }

    @Override
    public Integer selectStocksByProdId(Long prodId) {
        return presellMapper.selectStocksByProdId(prodId);
    }

    @Override
    public int updateStocksById(Long activityId, Integer prodCount) {
        return presellMapper.updateStocksById(activityId, prodCount);
    }

    @Override
    public int returnStocks(Long activityId, Integer prodCount) {
        return presellMapper.returnStocks(activityId, prodCount);
    }

    @Override
    public void cancelUnpayOrderByOrder(Long activityId, String orderNumber) {
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(orderNumber);
        for (OrderItem orderItem : orderItems) {
            presellMapper.returnStocks(activityId, orderItem.getProdCount());
            activityProdService.returnStocks(activityId, orderItem.getProdId(), orderItem.getProdCount());
            String key = ACTIVITY_SKU_STOCKS_PREFIX + activityId + "_" + orderItem.getProdId();
            // 清除库存的缓存
            RedisUtil.del(key);
            activityProdService.removeActivitySkuCache(activityId, orderItem.getProdId());
        }

    }

    @Override
    public PageVO<MicroreleaseProductSearchVo> selectPageActivityPresellByActivityIds(PageDTO page, List<String> activityIds, List<Long> activityType) {
        return PageUtil.doPage(page, () -> presellMapper.selectPageActivityPresellByActivityIds(activityIds, activityType));
    }

    @Override
    public ActivityProdDataDto getDataByActivityAndProdId(Long activityId, Long prodId) {
        return presellMapper.getDataByActivityAndProdId(activityId, prodId);
    }

    @Override
    public ActivityProdDataDto getDataByProdIds(Long pids) {
        return presellMapper.getDataByProdIds(pids);
    }

    @Override
    public ShopDealer getDealerByActivityId(Long activityId) {
        return presellMapper.getDealerByActivityId(activityId);
    }


}
